/****************************************************************************
  ECE 486 Project 1
  PDP-8 Simulator

  main.cpp

  Initialize the variables and fetech and decode instructions 
****************************************************************************/

#include <iostream>
#include <fstream>
#include <iomanip>
#include "stdafx.h"
#include "winmain.h"
#include "header.h"

using namespace std;

//initialize registers, counters and other variables
int initialize()
{
	int i;

	LB_AC = 0;
	MQ    = 0;
	PC    = 0;
	IR    = 0;
	MB    = 0;
	CPMA  = 0;
	SR    = 0;

	//inst  = 0;

	ANDcount   = 0;
	TADcount   = 0;
	ISZcount   = 0;
	DCAcount   = 0;
	JMScount   = 0;
	JMPcount   = 0;
	IOcount    = 0;
	microcount = 0;
	totalInst  = 0;
	extraMemCycCount = 0;
	totalCycCount    = 0;
	memWriteCount    = 0;
	memReadCount     = 0;

	debug = DEBUG;
	debugparam = DEBUGPARAM;
	debugfile = DEBUGFILE;

	for (i=0; i<4096; ++i)
		memory[i] = 0;
	

	return 0;
}


// Display register contents
int displayregs(int debugparam)
{
	if(!debugfile)
	{
		cout << "\n======================\n";
		cout << oct;
		cout << setfill('0') << setw(4);
		cout << "PC     : " << PC << endl;
		cout << dec;
		cout << "IR     : " << IR << endl;
		cout << oct;
		cout << "LB_AC  : ";
		cout << setfill('0') << setw(5);
		cout << LB_AC << 'o' << endl;
	}
	else
	{
		ofstream fout;

		fout.open("testoutput.txt",fstream::app);	//append testoutput.txt

		fout << "\n======================\n";
		fout << oct;
		fout << setfill('0') << setw(4);
		fout << "PC     : " << PC << endl;
		fout << dec;
		fout << "IR     : " << IR << endl;
		fout << oct;
		fout << "LB_AC  : ";
		fout << setfill('0') << setw(5);
		fout << LB_AC << 'o' << endl;
	}

	return 0;
}

int displaymemory(int debugparam)
{
	ofstream fout;
	
	switch(debugparam)
	{
	case 1:
	fout.open("test_pre.txt"); break;
	default:
	fout.open("test_post.txt"); break;
	}

	int i;

	for (i = 0; i < 4096; ++i)
	{
		fout << setfill('0') << setw(4);

		fout << oct << i << ' ';

		fout << setfill('0') << setw(6);

		fout << oct << memory[i] << endl;
	}

	fout.close();

	return 0;
}


// Fetch instructino from memory
unsigned short fetch()
{
	unsigned short inst;
	
	inst = memory[PC];
	createTrace(FETCH,PC++);

	return (inst & 007777);
}

// Decode and Execute the instruction
int decode(unsigned short inst, HWND hwnd)
{
	int ishalt = 0;

	// Decoding instruction
	IR = (inst & 007000) >> 9;

	// Execute instruction
	switch (IR)
	{
		case 0: AND(inst); ++ANDcount; break;
		case 1: TAD(inst); ++TADcount; break;
		case 2: ISZ(inst); ++ISZcount; break;
		case 3: DCA(inst); ++DCAcount; break;
		case 4: JMS(inst); ++JMScount; break;
		case 5: JMP(inst); ++JMPcount; break;
		case 6:  IO(inst,hwnd); ++IOcount;  break;
				case 7: 
				if(inst == 07402)
					ishalt = 1;
				else
					opcode7(inst);

				++microcount; break;
		default:;
	}
	
	if (IR <= 6)
		updateExtraMemCyc(inst);
	
	++totalInst;	//increment total instruction count

	return ishalt;
}

// Decode and Execute the instruction (console)
int decode(unsigned short inst) 
{
	if (inst & 007777)
	{
		// Decoding instruction
		IR = (inst & 007000) >> 9;

		// Execute instruction
		switch (IR)
		{
			case 0: AND(inst); ++ANDcount; break;
			case 1: TAD(inst); ++TADcount; break;
			case 2: ISZ(inst); ++ISZcount; break;
			case 3: DCA(inst); ++DCAcount; break;
			case 4: JMS(inst); ++JMScount; break;
			case 5: JMP(inst); ++JMPcount; break;
			case 6:  IO(inst); ++IOcount;  break;
			case 7: opcode7(inst); ++microcount; break;
			default:;
		}
		
		if (IR <= 6)
			updateExtraMemCyc(inst);
		
		++totalInst;	//increment total instruction count
	}

	return 0;
}

// Update extra memory cycle incurred by memory reference
int updateExtraMemCyc( unsigned short inst ) 
 { 
   unsigned short mask = 0777; 
   
   inst = inst & mask; 
  
   if( inst & 0400 ) 
     switch( inst ) 
     { 
       case 0410 : extraMemCycCount += 2; 
                   break; 
       case 0411 : extraMemCycCount += 2; 
                   break; 
       case 0412 : extraMemCycCount += 2; 
                   break; 
       case 0413 : extraMemCycCount += 2; 
                   break; 
       case 0414 : extraMemCycCount += 2; 
                   break; 
       case 0415 : extraMemCycCount += 2; 
                   break; 
       case 0416 : extraMemCycCount += 2; 
                   break; 
       case 0417 : extraMemCycCount += 2; 
                   break; 
         default : extraMemCycCount += 1; 
     } 

   if (debug && !debugfile) cout << "ExtraMemCycCount:" << extraMemCycCount << endl;
  
   return 0; 
 } 

